package com.moss.cloud.base.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moss.cloud.base.api.model.from.BaseFrom;
import com.moss.cloud.base.api.model.from.ChildrenFrom;
import com.moss.cloud.base.api.model.from.PositionFrom;
import com.moss.cloud.base.api.model.param.PositionParam;
import com.moss.cloud.base.api.model.vo.PositionVO;
import com.moss.cloud.base.biz.mapper.SysPositionMapper;
import com.moss.cloud.base.biz.model.SysPosition;
import com.moss.cloud.base.biz.service.ISysPositionService;
import com.moss.cloud.common.base.utils.PageUtil;
import com.moss.cloud.common.core.exception.SystemErrorType;
import com.moss.cloud.common.core.model.vo.BaseProTree;
import com.moss.cloud.common.core.utils.BooleanHandel;
import com.moss.cloud.common.core.utils.TreeUtil;
import com.moss.cloud.common.core.utils.UserContextHolder;
import com.moss.cloud.common.security.annotation.RequiresTenant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 职位管理业务实现
 *
 * @author 瑾年
 * @date 2023年12月19日
 */
@Slf4j
@Service
public class SysPositionServiceImpl extends ServiceImpl<SysPositionMapper, SysPosition> implements ISysPositionService {
    /**
     * 职位分页查询
     *
     * @param positionParam
     * @return
     */
    @Override
    @RequiresTenant
    public IPage<PositionVO> positionPage(PositionParam positionParam) {
        int maxLevel = this.maxLevel();
        Page<SysPosition> page = PageUtil.createPage(positionParam.getCurrent(), positionParam.getSize());
        IPage<SysPosition> positionIPage = this.page(page, new QueryWrapper<SysPosition>().lambda()
                .like(StringUtils.isNotBlank(positionParam.getPositionName()), SysPosition::getPositionName, positionParam.getPositionName())
                .eq(StringUtils.isNotBlank(positionParam.getPositionCode()), SysPosition::getPositionCode, positionParam.getPositionCode())
                .eq(SysPosition::getTenantId, UserContextHolder.getTenantId())
                .eq(SysPosition::getParentId, 0L));
        IPage<PositionVO> positionVOIPage = new Page<>();
        BeanUtils.copyProperties(positionIPage, positionVOIPage);
        List<PositionVO> positionVOS = CollectionUtils.isNotEmpty(positionIPage.getRecords()) ? positionIPage.getRecords().stream()
                .map(item -> this.positionVO(item, maxLevel)).collect(Collectors.toList()) : Collections.emptyList();
        positionVOIPage.setRecords(positionVOS);
        return positionVOIPage;
    }

    /**
     * 查询职位孩子节点数据
     *
     * @param childrenFrom
     * @return
     */
    @Override
    @RequiresTenant
    public List<PositionVO> childrenList(ChildrenFrom childrenFrom) {
        int maxLevel = this.maxLevel();
        List<SysPosition> positions = this.list(new QueryWrapper<SysPosition>().lambda()
                .eq(SysPosition::getParentId, childrenFrom.getParentId())
                .eq(SysPosition::getTenantId, UserContextHolder.getTenantId()));
        return CollectionUtils.isNotEmpty(positions) ? positions.stream().map(item -> this.positionVO(item, maxLevel))
                .collect(Collectors.toList()) : Collections.emptyList();
    }

    private PositionVO positionVO(SysPosition position, int maxLevel) {
        PositionVO positionVO = new PositionVO();
        BeanUtils.copyProperties(position, positionVO);
        positionVO.setIsLeaf(position.getLevel() == maxLevel ? Boolean.TRUE : Boolean.FALSE);
        return positionVO;
    }

    private int maxLevel() {
        QueryWrapper<SysPosition> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("MAX(level) AS level");
        return this.getOne(queryWrapper).getLevel();
    }

    /**
     * 职位树结构
     *
     * @param positionParam
     * @return
     */
    @Override
    @RequiresTenant
    public List<BaseProTree> positionTree(PositionParam positionParam) {
        List<SysPosition> positions = this.list(new QueryWrapper<SysPosition>().lambda()
                .like(StringUtils.isNotBlank(positionParam.getPositionName()), SysPosition::getPositionName, positionParam.getPositionName())
                .eq(StringUtils.isNotBlank(positionParam.getPositionCode()), SysPosition::getPositionCode, positionParam.getPositionCode())
                .eq(SysPosition::getTenantId, UserContextHolder.getTenantId()));
        List<BaseProTree> proTrees = CollectionUtils.isNotEmpty(positions) ? positions.stream().map(item -> {
            BaseProTree baseProTree = new BaseProTree();
            baseProTree.setParentId(item.getParentId());
            baseProTree.setKey(item.getId());
            baseProTree.setLabel(item.getPositionName());
            baseProTree.setValue(item.getId());
            baseProTree.setTitle(item.getPositionName());
            return baseProTree;
        }).collect(Collectors.toList()) : Collections.emptyList();
        return CollectionUtils.isNotEmpty(proTrees) ? TreeUtil.toTree(proTrees, 0L,
                BaseProTree::getKey, BaseProTree::getParentId, BaseProTree::setChildren) : Collections.emptyList();
    }

    /**
     * 职位详情
     *
     * @param baseFrom
     * @return
     */
    @Override
    public SysPosition position(BaseFrom baseFrom) {
        return this.getById(baseFrom.getId());
    }

    /**
     * 新增职位
     *
     * @param positionFrom
     * @return
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public boolean savePosition(PositionFrom positionFrom) {
        SysPosition position = new SysPosition();
        BeanUtils.copyProperties(positionFrom, position);
        position.setTenantId(UserContextHolder.getTenantId());
        return this.save(position);
    }

    /**
     * 更新职位
     *
     * @param positionFrom
     * @return
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePosition(PositionFrom positionFrom) {
        BooleanHandel.trueThrow(Objects.isNull(positionFrom.getId())).throwMessage(SystemErrorType.PRIMARY_KEY);
        this.checkDataPermission(positionFrom.getId());
        SysPosition position = new SysPosition();
        BeanUtils.copyProperties(positionFrom, position);
        return this.updateById(position);
    }

    /**
     * 删除职位
     *
     * @param baseFrom
     * @return
     */
    @Override
    @RequiresTenant
    @Transactional(rollbackFor = Exception.class)
    public boolean removePosition(BaseFrom baseFrom) {
        this.checkDataPermission(baseFrom.getId());
        return this.removeById(baseFrom.getId());
    }

    private void checkDataPermission(Long id) {
        Long tenantId = UserContextHolder.getTenantId();
        SysPosition sysPosition = this.getById(id);
        BooleanHandel.trueThrow(Objects.isNull(sysPosition)).throwMessage(SystemErrorType.DATE_EMPTY);
        BooleanHandel.trueThrow(!tenantId.equals(sysPosition.getTenantId())).throwMessage(SystemErrorType.NOT_BELONG_TENANT);
    }

    /**
     * 职位代号查询职位数量
     *
     * @param code
     * @return
     */
    @Override
    public long positionByCode(String code) {
        return this.count(new QueryWrapper<SysPosition>().lambda()
                .eq(SysPosition::getTenantId, UserContextHolder.getTenantId())
                .eq(SysPosition::getPositionCode, code));
    }
}
